home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
wmv12s.zip
/
MV.C
< prev
next >
Wrap
Text File
|
1993-01-04
|
10KB
|
359 lines
/* move subdirectories
** Written by Peter Wu; July 86.
** compile with cc mv /ze
*/
#define LINT_ARGS
#define ALLOC 26 /* starting cluster number in directory entry */
#define PLEN 200 /* max path len */
#include <dos.h>
#include "dta.h"
#include "peek.h"
#include <conio.h>
unsigned char func32h();
unsigned short findir();
unsigned short clus2sec();
char *readsec();
char lastc(char *);
/* external var */
extern int
num_sec, /* number of sectors buffered */
brk_st; /* orginal break status */
/* source & dest must be normalized
** mydta1 contains dta of source
*/
mvdir(mydta1,source,dest) /* move subdirectory */
union dtbuf mydta1;
char *source, *dest;
{
unsigned short sector1, sector2, offset1, offset2, clus1, clus2,
d1, d2, status, *p1, *p2, ds1, ds2, bps, parent, drv;
char *secbuf1, *secbuf2, *secbuf3, cpath[PLEN];
union dtbuf mydta2;
/* make sure source is not a root directory */
if (lastc(source) == '\\') {
cputs("move root directory? You're joking!\n\015");
exit(1);
}
/* make sure source is not predesessor of destination */
if (apreb(source, dest)) {
/* this will create a directory loop if allowed to go on or
** it's a redundant rename to itself (e.g. mv \ha\. \)
*/
cputs("not moved to avoid loop or redundancy\n\015");
return -1;
}
/* see if source is a predesessor of current directory */
drv = toupper(source[0]) - '@';
current(drv,cpath);
if ( apreb(source,cpath) ) {
cputs("not moved to preserve current directory\n\015");
return -2;
}
/* there should be a way to test if source is a predesessor of
** a 'subst' drive's current directory
*/
bset(0); /* do not allow user to break during this portion */
status = mkdir(dest);
if (status) {
cputs("can't; file exists already/disk write protected\n\015");
exit(1);
}
status = ffmf(dest, A_DIR, &mydta2);
if (status) {
cputs("error on ffmf after mkdir\n\015");
error("mvdir", 0);
}
num_sec = 0; /* clear sector buffers */
sector1 = findir(mydta1, &offset1, &d1, &secbuf1);
if (sector1 < 0) {
cputs("cannot find source directory\n\015");
error("mvdir", 0);
}
sector2 = findir(mydta2, &offset2, &d2, &secbuf2);
if (sector2 < 0) {
cputs("cannot get info on destination directory\n\015");
error("mvdir", 0);
}
if (d1 != d2) { /* this should have been detected earlier */
cputs("source and destination has to be on the same drive\n\015");
exit(1);
}
/* now switch the starting cluster of the two directories */
p1 = (unsigned short *) (secbuf1 + offset1 + ALLOC);
p2 = (unsigned short *) (secbuf2 + offset2 + ALLOC);
clus1 = *p1;
clus2 = *p2;
#ifdef debug
printf("clus1=%4x clus2=%4x\n", clus1, clus2);
#endif
*p1 = clus2;
*p2 = clus1;
status = flirt(d1-1, sector1); /* mark sector dirty */
if (status) {
cputs("error in flirt\n\015");
error("mvdir", 0);
}
status = flirt(d1-1, sector2); /* mark sectors as dirty */
if (status) {
cputs("error in flirt\n\015");
error("mvdir", 0);
}
/* now we must find the cluster# of the parent directory of the
** destination directory (slot number two in clus2) so we can put
** it in the source directory (which will become the new destination
** directory.
*/
ds1 = clus2sec(d1, clus1, &bps); /* sector# of cluster 1 */
ds2 = clus2sec(d1, clus2, &bps); /* sector# of cluster 2 */
secbuf3 = readsec(d1-1,ds2);
if (secbuf3 == (char *) 0) {
cputs("error in calling readsec\n\015");
error("mvdir", 0);
}
parent = * (unsigned short *) (secbuf3 + 32 + ALLOC);
#ifdef debug
printf("parent is %4x\n", parent );
#endif
/* now write this into source dir */
secbuf3 = readsec(d1-1,ds1);
if (secbuf3 == (char *) 0) {
cputs("error in calling readsec\n\015");
error("mvdir", 0);
}
*(unsigned short *) (secbuf3 + 32 + ALLOC) = parent;
status = flirt(d1-1,ds1);
if (status) {
cputs("error in flirt\n\015");
error("mvdir", 0);
}
/* now write back all three (or less) modified sectors */
status = writesec(d1-1,ds1); /* the cluster containing parent pointer */
if (status) { /* what could cause this to happen? */
cputs("error in writing first modified sector\n\015");
error("mvdir", 1);
}
status = writesec(d1-1,sector2);
if (status) { /* it's impossible for this to happen */
cputs("error in writing second modified sector\n\015");
error("mvdir", 1);
}
status = writesec(d1-1,sector1);
if (status) { /* this is also impossible */
cputs("error in writing third modified sector\n\015");
error("mvdir", 1);
}
bdos(0xd,0,0); /* reset disk - neccessary for rmdir to work since DOS'
** buffer now contains invalid information (it didn't
** know that the disk was modified).
*/
status = rmdir(source); /* this dir should be empty now */
if (status) {
putn(
"Oops!\n\015",
"cannot remove old directory \"", source, "\"\n\015",
"Maybe one of your `subst' disk is using this directory. If this is\n\015",
"the case, remove the subst disk and then remove this directory.\n\015", 0);
exit(1);
}
bset(brk_st); /* restore break status */
return 0; /* no error */
}
unsigned short findir(mydta, offsetp, drv, secbuf)
char **secbuf;
unsigned short *offsetp;
unsigned int *drv;
union dtbuf mydta;
{
unsigned int status, i, j, offset, sector, cluster, tmp, bps;
union REGS inregs, outregs;
struct SREGS segregs;
char c, dir[13]; /* directory entry formatted like X.Y not "X Y " */
if (mydta.dos.attr != A_DIR) { /* guard against programmer's error */
putn(mydta.dos.fn, " is not a directory\n\015",0);
error("findir", 0);
}
/* now find the cluster where the searched directory is */
cluster = mydta.dos.clusl + (mydta.dos.clush << 8);
/* now convert the cluster number to sector number */
sector = clus2sec(mydta.dos.drv_no, cluster, &bps);
/* calculate directory entry offset in the sector */
offset = ((mydta.dos.sloth << 8) + mydta.dos.slotl) * 32;
sector += offset / bps; /* normalize sector & offset */
offset %= bps;
#ifdef debug
printf("dir at sector %d\n", sector);
#endif
*secbuf = readsec(mydta.dos.drv_no - 1, sector);
if (*secbuf == (char *) 0) {
cputs("error in calling readsec\n\015");
error("findir", 0);
}
#ifdef debug
printf("First 11 bytes in sector: %11.11s\n", *secbuf+offset);
printf("Fn returned by ffmf: %11.11s\n", mydta.fn);
#endif
/* redundant check to see if we have the correct directory entry */
/* first format the directory entry name in this form "*.*" instead of
** "???????????"
*/
i=0;
c = (*secbuf)[offset];
while ((c != ' ') && (i < 8)) { /* copy the first 8 characters */
dir[i] = c;
i++;
c = (*secbuf)[offset+i];
}
j = 8;
c = (*secbuf)[offset+j];
if (c != ' ') { /* sub-dir name has extension */
/* now add '.' and copy the extension */
dir[i] = '.';
i++;
while ((c != ' ') && (j < 11)) {
dir[i] = c;
i++;
j++;
c = (*secbuf)[offset + j];
}
}
dir[i] = '\0'; /* terminate string */
#ifdef debug
printf("formatted directory entry string: %s\n", dir);
#endif
if (strcmp(mydta.dos.fn, dir) == 0) {
#ifdef debug
printf("Directory entry found!\n");
#endif
} else {
cputs("cannot find directory entry\n\015");
error("findir", 0);
}
/* redundant check to make sure file size of directory is zero */
if (*(unsigned long *)(*secbuf+offset+28) != 0L) {
cputs("found directory with size > 0\n\015");
error("findir", 0);
}
*offsetp = offset;
*drv = mydta.dos.drv_no;
return sector;
}
unsigned short clus2sec(drv, clus_no, pbps) /* convert cluster to sector */
unsigned short clus_no, *pbps, drv;
{
unsigned char status;
static unsigned short spc=0, ss, bps, tabseg, taboff;
unsigned short sector;
if (spc == 0) { /* first time function is called */
status = func32h(drv, &tabseg, &taboff); /* See PC Tech Journal */
if (status == 0xff) {
cputs("func32h: invalid drive: "); putch(drv+'A'); cputs("\n\015");
error("clus2sec", 0);
}
spc = peekb(tabseg,taboff+4)+1; /* sector per cluster */
ss = peekw(tabseg,taboff+11); /* starting data sector */
bps = peekw(tabseg,taboff+2); /* bytes per sector */
#ifdef debug
printf("drive #: %d\n", drv);
printf("sectors per cluster: %d\n", spc);
printf("# allocation units: %d\n", peekw(tabseg,taboff+13)-1 );
printf("sector size: %d\n", bps);
printf("starting sector: %d\n", ss);
#endif
}
*pbps = bps; /* return this value */
if (clus_no == 0) {
#ifdef debug
printf("parent directory is root! - special case\n");
#endif
sector = peekw(tabseg,taboff+16); /* first sector of root directory */
} else {
sector = (clus_no - 2) * spc + ss; /* see DOS Tech. Ref */
}
return sector;
}
/* apreb test to see if patha is equal to or is a predessesor of pathb
** This is used to test whether moving a directory would result
** in a directory loop condition and also whether the source
** directory is a predessor of the current path (can't delete
** source directory in this case, so don't move)
**
** patha and pathb must be normalized paths
** E.g.
** apreb("A:\DEF", "A:\DEF") is true
** apreb("A:\DEF", "A:\DEF\GHI") is also true
** apreb("A:\DEF", "A:\DEFG") is false
*/
apreb(patha, pathb)
char *patha, *pathb;
{
int i, lena, lenb;
char c;
lena = strlen(patha);
lenb = strlen(pathb);
if (lena > lenb) { /* if patha is longer, it can't be a predessesor */
return 0;
}
c = pathb[lena]; /* if patha is a predessesor, c should be '\\' or '\0' */
if ((c != '\\') && (c != '\0')) {
return 0;
}
if (strncmp(patha, pathb, lena)) { /* not equal */
return 0;
}
return 1;
}